/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 *
 * @author коля
 */
public class RTL {
    final private static int OBJ=0;
    final private static int INT=1;
    final private static int STR=2;
    final private static int ARR=3;
    
    public static void printStmt(UnivBaseClass a){
        if(a.var_type==ARR){
            for(int i=0;i<a.var_arr.length;i++){
                switch(a.var_arr[i].var_type){
                    case INT: // Integer
                        System.out.print(a.var_arr[i].var_int);
                        if(i<a.var_arr.length-1)
                            System.out.print(", ");
                        break;
                    case STR: // Integer
                        System.out.print(a.var_arr[i].var_str);
                        if(i<a.var_arr.length-1)
                            System.out.print(", ");
                        break;
                }
            }
        }
        else{
            switch(a.var_type){
                    case INT: // Integer
                        System.out.print(a.var_int);
                        break;
                    case STR: // Integer
                        System.out.print(a.var_str);
                        break;
                }
        }
    }
    public static UnivBaseClass plus(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        if( l.var_type != r.var_type || l.var_type != INT&&l.var_type != STR)
            throw new VerifyError("Plus error");
        else{
            switch(l.var_type){
                case INT:
                    res.var_int = l.var_int + r.var_int; 
                    res.var_type = INT;
                    break;
                case STR: 
                    res.var_int = Integer.parseInt(l.var_str) + Integer.parseInt(r.var_str);
                    res.var_type = INT;
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass minus(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        if( l.var_type != r.var_type || l.var_type != INT&&l.var_type != STR)
            throw new VerifyError("Minus error");
        else{
            switch(l.var_type){
                case INT:
                    res.var_int = l.var_int - r.var_int; 
                    res.var_type = INT;
                    break;
                case STR: 
                    res.var_int = Integer.parseInt(l.var_str) - Integer.parseInt(r.var_str);
                    res.var_type = INT;
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass mul(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        if( l.var_type != r.var_type || l.var_type != INT)
            throw new VerifyError("Mul error");
        else{
            switch(l.var_type){
                case INT:
                    res.var_int = l.var_int * r.var_int; 
                    res.var_type = INT;
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass div(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        if( l.var_type != r.var_type || l.var_type != INT)
            throw new VerifyError("Div error");
        else{
            switch(l.var_type){
                case INT:
                    res.var_int = l.var_int / r.var_int; 
                    res.var_type = INT;
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass less(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT && l.var_type != STR)
           throw new VerifyError("Less error");
        else{
            boolean bufBool;
            switch(l.var_type){
                case INT:
                    switch(r.var_type){
                        case INT:
                            bufBool= l.var_int < r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= l.var_int < Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
                case STR:
                    switch(r.var_type){
                        case INT:
                            bufBool= Integer.parseInt(l.var_str) < r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= Integer.parseInt(l.var_str) < Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass more(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT && l.var_type != STR)
           throw new VerifyError("More error");
        else{
            boolean bufBool;
            switch(l.var_type){
                case INT:
                    switch(r.var_type){
                        case INT:
                            bufBool= l.var_int > r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= l.var_int > Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
                case STR:
                    switch(r.var_type){
                        case INT:
                            bufBool= Integer.parseInt(l.var_str) > r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= Integer.parseInt(l.var_str) > Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass equal(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT && l.var_type != STR)
           throw new VerifyError("Equal error");
        else{
            boolean bufBool;
            switch(l.var_type){
                case INT:
                    switch(r.var_type){
                        case INT:
                            bufBool= l.var_int == r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= l.var_int == Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
                case STR:
                    switch(r.var_type){
                        case INT:
                            bufBool= Integer.parseInt(l.var_str) == r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= Integer.parseInt(l.var_str) == Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass concatenation(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type=STR;
        if( l.var_type != r.var_type || l.var_type != STR)
            throw new VerifyError("Concatenation error");
        else{
            res.var_str = l.var_str + r.var_str; 
        }
        return res;
    }
    public static UnivBaseClass notEqual(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT && l.var_type != STR)
           throw new VerifyError("notEqual error");
        else{
            boolean bufBool;
            switch(l.var_type){
                case INT:
                    switch(r.var_type){
                        case INT:
                            bufBool= l.var_int != r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= l.var_int != Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
                case STR:
                    switch(r.var_type){
                        case INT:
                            bufBool= Integer.parseInt(l.var_str) != r.var_int; 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                        case STR:
                            bufBool= Integer.parseInt(l.var_str) != Integer.parseInt(r.var_str); 
                            if(bufBool==true)
                                res.var_int=1;
                            else
                                res.var_int=0;
                            break;
                    }
                    break;
            }
        }
        return res;
    }
    public static UnivBaseClass uminus(UnivBaseClass r){

        UnivBaseClass res = new UnivBaseClass();
        if(r.var_type != INT)
            throw new VerifyError("Uminus error");
        else{
            res.var_type = INT;
            res.var_int = -r.var_int; 
        }
        return res;
    }
    public static UnivBaseClass uplus(UnivBaseClass r){

        UnivBaseClass res = new UnivBaseClass();
        if(r.var_type != INT)
            throw new VerifyError("Uplus error");
        else{
            res.var_type = INT;
            res.var_int = +r.var_int; 
        }
        return res;
    }
    public static UnivBaseClass orOper(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT )
           throw new VerifyError("OrOper error");
        else{
            if(l.var_int==0 &&r.var_int==0)
                res.var_int=0;
            else
                res.var_int=1;
        }
        return res;
    }
    public static UnivBaseClass andOper(UnivBaseClass l, UnivBaseClass r){
        UnivBaseClass res = new UnivBaseClass();
        res.var_type = INT;
        if(l.var_type != INT )
           throw new VerifyError("OrOper error");
        else{
            if(l.var_int==1 && r.var_int==1)
                res.var_int=1;
            else
                res.var_int=0;
        }
        return res;
    }
    public static UnivBaseClass notOper(UnivBaseClass r){

        UnivBaseClass res = new UnivBaseClass();
        res.var_type=INT;
        if(r.var_type != INT)
            throw new VerifyError("NotOper error");
        else{
            if(r.var_int==0)
                res.var_int=1;
            else
                res.var_int=0;
        }
        return res;
    }
    public static void arrayAssign(UnivBaseClass arr, UnivBaseClass ind, UnivBaseClass val) {
        int curInd = ind.var_int;
        UnivBaseClass[] newArr;
        if(arr.var_arr == null) {
            arr.var_arr = new UnivBaseClass[curInd+1];
        }
        if( curInd >= arr.var_arr.length ) {
            newArr = new UnivBaseClass[curInd + 1];
            for(int i = 0; i < arr.var_arr.length; i++) {
                newArr[i] = arr.var_arr[i];
            }
            arr.var_arr = newArr;
        }
        arr.var_arr[curInd] = val;
        
        
    }
    public static UnivBaseClass arrayElement(UnivBaseClass arr, UnivBaseClass ind) {
        int curInd = ind.var_int;
        return arr.var_arr[curInd];
    }
    public static int ifExprToInt(UnivBaseClass a){
        int buf = 0;
        switch(a.var_type){
            case OBJ:
                buf = 1;   
                break;
            case INT: 
                if(a.var_int == 0)
                    buf = 0;
                else
                    buf = 1;
                break;
            case STR:
                if("".equals(a.var_str))
                    buf = 0;
                else
                    buf = 1;
                break;
            case ARR: 
                if(a.var_arr.length == 0)
                    buf = 0;
                else
                    buf = 1;
                break;
        }
        return buf;
    }
}
